
var RSNIFFER_PORT = 161;
// Default dir to look for resources
var BINDIR = SCRIPT_ORIGIN;

var RSNIFFER = {
    conn:     null,
    timeout:  null,
    socket:   null,
    asm:      null,
    asmfile:  null,
    mote:     null,

    moteAddr: null,          // IN:
    moteDLL: 'iris',         // IN:
    serial:   null,
    framesRecived: false,
    
    main: function (moteAddr) {
	this.moteAddr = moteAddr;
	var result = Saguaro.getProcess(null, SCB);
	if( result.isERR() )
	    this.failed("Connect failed: %s", result.toString());
	this.conn = result.getData();
	printf("Connected to: %s\n", this.conn);
	if( this.moteAddr != null ) {
	    this.mote = Sonoran.Registry.lookupMote(this.moteAddr);
	    if( this.mote==null )
		this.failed("Mote <%s> does not exist!",this.moteAddr);
	    //XXX
	    return;
	}
       var settings = new Sonoran.MoteSettings();
       settings.dll = this.moteDLL;
       result = Sonoran.createMote(settings, 1, SCB);
	if( result.isERR() )
	    this.failed("Failed to create a mote: %s", result.toString());
	this.mote = result.getMotes()[0]; 
	printf("Created mote <%s> running sniffer assembly.\n", this.mote);
        // load the assembly
	this.asmfile = BINDIR+'/kaixo-10.0.sba';
	if (!OSFile.exists(this.asmfile)) {
	    this.failed("Missing file: %s", this.asmfile);
	    return;
	}	
        this.asm = new Sonoran.Assembly(OSFile.readFully(this.asmfile));
        result = this.mote.getMOMA().load(this.asm, null, SCB);
	if( result.isERR() )
	    this.failed("Load of <%s> onto mote <%s> failed: %s", this.asmfile, this.mote, result.toString());
	this.openSocket();
    },

    openSocket: function (addr) {
	var self = this;
	var socket = this.socket = new Sonoran.Socket();
	var setupTimeout = function () {
            if (self.timeout)
                Timer.remove(self.timeout);
	    self.timeout = Timer.timeoutIn(15000, function () {
					      // printf("No sniffed frames yet - to quit enter \"quit\" any time");
					   });
	};
	socket.onOpen = function(status) {
	    // socket's ready, send first packet
	    printf("Registering with sniffer %s on port %d\n", self.mote, RSNIFFER_PORT); 
	    socket.send(Formatter.pack("uu", [0, 0]), self.mote, RSNIFFER_PORT);
	    setupTimeout();
	};
	socket.onClose = function(status) {
	    // socket was closed
	    printf("UDP socket was closed: ", status);
	    Runtime.exit(0);
	};
	socket.onData = function(blob) {
	    // received a packet
	    //  4: time
	    //  1: LQI
	    //  1: RSSI
	    //  1: LEN
	    //  n: data
	    setupTimeout();
	    var ex;
	    println(""+blob.data.length);
	    try {
	    var x = Formatter.unpack("1u1u1u1u1u1u1u1u1u1u", blob.data,0);
		var time,lqi,rssi,len,data;
		if( blob.data.length==4 ) {
		    time = Formatter.unpack("4u", blob.data);
		    printf("1sec = %d ticks\n", time[0]);
		    return;
		}
		/*if( blob.data.length < 7 ) {
		    printf("Received malformed UDP message from rsniffer assembly: <%H>\n", blob.data);
		    return;
		}
                var x = Formatter.unpack("4u1u1u1u<d", blob.data,0);
		var time = x[0];
                var lqi = x[1];
                var rssi = x[2];
                var len = x[3];
                var data = x[4];
		time = sprintf("%3d:%02d.%03d.%03d",
			       (time/(60*1000000))|0,
			       ((time/1000000)%60)|0,
			       ((time/1000)%1000)|0,
			       (time%1000)|0);
		var n = time.length;
		var last = this.lasttime;
		this.lasttime = time;
		if( last != null ) {
		    var j=0;
		    for( var i=0; i<n; i++ ) {
			var c = last.charAt(i);
			if( c == '.' ) j=i+1;
			if( last.charAt(i) != time.charAt(i) ) {
			    time = sprintf("%*s",n,time.substr(j));
			    break;
			}
		    }
		}*/
		if( lqi==0 && len==0 ) {
			printf("WASA2");
		    printf("%s  LQI=---  RSSI=%-3d ---\n", time, rssi);
		} else {
			//x = Formatter.unpack("1u1u1u1u1u1u1u", data);
			nodoEmisor = x[0];
			nodoReceptor = x[1];
			nodoCamino = x[2];
			
			if ( x[3] == 1 ) {
			//nodo envia reputacion de otro nodo	
			nodoReputacion = x[4];
			reputacion = x[5];
			printf("Nodo %01X envia reputacion respecto al nodo %01X, la reputacion=%01X.\n",nodoEmisor,nodoReputacion,reputacion);
			} else if (x[3] == 2) {
			//nodo envia alarma
			nodoEnviaAlarma = x[4];
			nodoCausaAlarma = x[5];
			Alarma = x[6]; 
			printf("Nodo %X envia alarma por causa=%X provocado por nodo=%X.\n",nodoEnviaAlarma,Alarma,nodoCausaAlarma);
			} else if (x[3] == 3){
			//nodo envia estado
			nodo = x[4];
			estadoRed = x[5];
			printf("Nodo %X informa de estado=%X.\n",nodo,estadoRed);
			}




/*
			var nodoEmisor,nodoReceptor,nodoCamino,accion,opcion1,opcion2,opcion3;
			x = Formatter.unpack("1u1u1u1u1u1u1u", data);
			nodoEmisor = x[1];
			//[nodoEmisor,nodoReceptor,nodoCamino,accion,opcion1,opcion2,opcion3] = Formatter.unpack("1u1u1u1u1u1u1u", data);
			printf("zero=%01X bat=%02x",nodoEmisor,x[1]);
		    printf("%s  LQI=%-3d  RSSI=%-3d %H\n", time, lqi, rssi, data);*/
		}
		if( len > 9 ) {;
		    var fcf,fca,seq,pan,dst,src;
		    x = Formatter.unpack("1u1u1u2uL2uL2uL", data);
                    [fcf,fca,seq,pan,dst,src] = Formatter.unpack("1u1u1u2uL2uL2uL", data);
		    printf("%34sFCF=%02X FCA=%02X SEQ=%02X PAN=%04X DST=%04X SRC=%04X\n",
			   "",x[0],x[1],x[2],x[3],x[4],x[5]);

		}
	    } catch (ex) {
		printf("Internal error: failed to unpack UDP message from rsniffer:\n"+
		       " UDP data: <%H>\n", blob.data);
	    }
	};

	socket.open();
    },

    failed: function(text) {
	println(svprintf(text, 1, arguments));
	Runtime.exit(1);
    }
};

if( ARGV[0]!=null && /^-(-?h(elp)?|\?)$/.exec(ARGV[0]) ) {
    println("usage sonoran runsniffer [serialport]\n");
    Runtime.exit(1);
}
if( ARGV.length==0 ) {
    println("Creating an iris simulation mote and loading rsniffer..");
} else {
    RSNIFFER.serial = ARGV[0];
    println("Attaching to serial port '%s' and loading rsniffer..", ARGV[0]);
}
RSNIFFER.main();
